using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.Configuration;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net;
using ScrewTurn.Wiki.PluginFramework;
using System.Text;

namespace ScrewTurn.Wiki {

	public partial class Admin : BasePage {

		#region ViewStateCompression

		protected override object LoadPageStateFromPersistenceMedium() {
			if(Settings.EnableViewStateCompression) {
				string viewState = Request.Form["__VSTATE"];
				byte[] bytes = Convert.FromBase64String(viewState);
				bytes = Compressor.Decompress(bytes);
				LosFormatter formatter = new LosFormatter();
				return formatter.Deserialize(Convert.ToBase64String(bytes));
			}
			else {
				return base.LoadPageStateFromPersistenceMedium();
			}
		}

		protected override void SavePageStateToPersistenceMedium(object viewState) {
			if(Settings.EnableViewStateCompression) {
				LosFormatter formatter = new LosFormatter();
				StringWriter writer = new StringWriter();
				formatter.Serialize(writer, viewState);
				string viewStateString = writer.ToString();
				byte[] bytes = Convert.FromBase64String(viewStateString);
				bytes = Compressor.Compress(bytes);
				ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
			}
			else {
				base.SavePageStateToPersistenceMedium(viewState);
			}
		}

		#endregion

		#region Initialization

		protected void Page_Load(object sender, EventArgs e) {
			Page.Title = Resources.Messages.AdminTitle + " - " + Settings.WikiTitle;

			if(!string.IsNullOrEmpty(Request.UserAgent) && Request.UserAgent.ToLowerInvariant().Contains("konqueror") ||
				Request.UserAgent.ToLowerInvariant().Contains("safari")) {
				lblBrowserSupport.Visible = true;
			}

			if(SessionFacade.LoginKey == null) {
				Response.Redirect("Login.aspx?Redirect=Admin.aspx" + (Request["ActivationMode"] != null ? Tools.UrlEncode("?ActivationMode=1") : ""));
			}

			if(!SessionFacade.Admin) {
				Response.Redirect("AccessDenied.aspx");
			}

			if(!SessionFacade.Username.Equals("admin") && !Settings.ConfigVisibleToAdmins) {
				btnSelectConfig.Visible = false;
			}
			else if(!SessionFacade.Username.Equals("admin")) {
				chkConfigVisibleToAdmins.Enabled = false;
			}

			if(!Page.IsPostBack) {
				if(SessionFacade.AdminView >= 0) {
					mlvAdmin.ActiveViewIndex = SessionFacade.AdminView;
				}
				else {
					mlvAdmin.ActiveViewIndex = 9;
					SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
				}
				if(Request["ActivationMode"] != null) {
					mlvAdmin.ActiveViewIndex = 0;
					SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
					chkViewActive.Checked = false;
				}
				PrintFileEditing();
				PrintSystemStatus();
				PrintDateTimeFormats();
				PrintStrings();
				SetupButtons();
				LoadUsers();
				LoadPages(true);
				LoadConfig();
				LoadSnippets();
				LoadCategories();
				LoadNavPaths();
				LoadProviders();
				LoadDlls();
				LoadRegExp();
				LoadValidationLocalizations();
			}

		}

		private void LoadUsers() {
			Users users = Users.Instance;
			lstUsers.Items.Clear();
			for(int i = 0; i < users.AllUsers.Count; i++) {
				if(users.AllUsers[i].Admin) {
					if(chkViewAdmins.Checked) {
						if(users.AllUsers[i].Active) {
							if(chkViewActive.Checked) {
								lstUsers.Items.Add(new ListItem(PrintUser(users.AllUsers[i]), users.AllUsers[i].Username));
							}
						}
						else {
							if(chkViewInactive.Checked) {
								lstUsers.Items.Add(new ListItem(PrintUser(users.AllUsers[i]), users.AllUsers[i].Username));
							}
						}
					}
				}
				else {
					if(chkViewUsers.Checked) {
						if(users.AllUsers[i].Active) {
							if(chkViewActive.Checked) {
								lstUsers.Items.Add(new ListItem(PrintUser(users.AllUsers[i]), users.AllUsers[i].Username));
							}
						}
						else {
							if(chkViewInactive.Checked) {
								lstUsers.Items.Add(new ListItem(PrintUser(users.AllUsers[i]), users.AllUsers[i].Username));
							}
						}
					}
				}
			}
		}

		private string PrintUser(UserInfo user) {
			string shift = "";
			if(Request.Cookies[Settings.CultureCookieName] != null) shift = Request.Cookies[Settings.CultureCookieName]["T"];

			string displayName = user.ToString();
			if(displayName.Contains(user.GetType().ToString()) || string.IsNullOrEmpty(displayName)) displayName = user.Username;
			StringBuilder sb = new StringBuilder(displayName);
			if(displayName != user.Username) sb.AppendFormat(" ({0})", user.Username);
			if(!user.Active) sb.Append(", Inactive");
			if(user.Admin) sb.Append(", Admin");
			sb.AppendFormat(" ({0})", user.Email);
			sb.AppendFormat(" [{0}]", user.Provider.Information.Name);
			sb.AppendFormat(" {0}", Tools.AlignWithPreferences(user.DateTime, shift).ToString(Settings.DateTimeFormat));
			return sb.ToString();
		}

		private void LoadPages(bool cleanBackupList) {
			Pages pages = Pages.Instance;
			lstPages.Items.Clear();
			for(int i = 0; i < pages.AllPages.Count; i++) {
				if(pages.AllPages[i].Status == PageStatus.Locked) {
					if(chkViewLocked.Checked) {
						lstPages.Items.Add(new ListItem(pages.AllPages[i].ToString(), pages.AllPages[i].Name));
					}
				}
				else if(pages.AllPages[i].Status == PageStatus.Public) {
					if(chkViewPublic.Checked) {
						lstPages.Items.Add(new ListItem(pages.AllPages[i].ToString(), pages.AllPages[i].Name));
					}
				}
				else {
					if(chkViewNormal.Checked) {
						lstPages.Items.Add(new ListItem(pages.AllPages[i].ToString(), pages.AllPages[i].Name));
					}
				}
			}
			if(cleanBackupList) {
				lstPageBackups.Items.Clear();
				lstPageBackups.Items.Add(new ListItem(" --- ", ""));
				btnDeleteAllBackups.Enabled = false;
				btnDeleteOlderBackups.Enabled = false;
				btnRollback.Enabled = false;
			}
		}

		private void LoadConfig() {
			txtWikiTitle.Text = Settings.WikiTitle;
			txtMainUrl.Text = Settings.MainUrl;

			string[] themes = Tools.AvailableThemes;
			lstTheme.Items.Clear();
			for(int i = 0; i < themes.Length; i++) {
				lstTheme.Items.Add(new ListItem(themes[i], themes[i]));
				if(lstTheme.Items[i].Value.Equals(Settings.Theme)) {
					lstTheme.Items[i].Selected = true;
				}
			}

			txtContactEmail.Text = Settings.ContactEmail;
			txtSenderEmail.Text = Settings.SenderEmail;
			txtSmtpServer.Text = Settings.SmtpServer;
			txtSmtpUsername.Text = Settings.SmtpUsername;
			//txtSmtpPassword.Text = Settings.SmtpPassword; // This is not rendered by ASP.NET, use "value" attribute instead
			txtSmtpPassword.Attributes.Add("value", Settings.SmtpPassword);
			txtSmtpPort.Text = Settings.SmtpPort != -1 ? Settings.SmtpPort.ToString() : "";
			chkSmtpSsl.Checked = Settings.SmtpSsl;

			lstDefaultPage.Items.Clear();
			Pages pages = Pages.Instance;
			bool sel = false; // Select only ONE page
			for(int i = 0; i < pages.AllPages.Count; i++) {
				lstDefaultPage.Items.Add(new ListItem(pages.AllPages[i].Name, pages.AllPages[i].Name));
				if(!sel && lstDefaultPage.Items[i].Value.Equals(Settings.DefaultPage)) {
					sel = true;
					lstDefaultPage.Items[i].Selected = true;
				}
			}

			chkEnableDoubleClickEditing.Checked = Settings.EnableDoubleClickEditing;
			chkDisableBreadcrumbsTrail.Checked = Settings.DisableBreadcrumbsTrail;
			chkProcessSingleLineBreaks.Checked = Settings.ProcessSingleLineBreaks;

			// This feature is currently DISABLED
			//if(Settings.KeptBackupNumber >= 0) txtKeptBackupsNumber.Text = Settings.KeptBackupNumber.ToString();
			//else txtKeptBackupsNumber.Text = "";

			txtDateTimeFormat.Text = Settings.DateTimeFormat;

			lstDefaultLanguage.Items.Clear();
			lstDefaultLanguage.Items.Add(new ListItem("English", "en-US"));
			for(int i = 0; i < Tools.AvailableCultures.Length; i++) {
				lstDefaultLanguage.Items.Add(new ListItem(Tools.AvailableCultures[i].Split('|')[1], Tools.AvailableCultures[i].Split('|')[0]));
			}
			for(int i = 0; i < lstDefaultLanguage.Items.Count; i++) {
				lstDefaultLanguage.Items[i].Selected = false;
				if(lstDefaultLanguage.Items[i].Value.Equals(Settings.DefaultLanguage)) {
					lstDefaultLanguage.Items[i].Selected = true;
					break;
				}
			}

			for(int i = 0; i < lstDefaultTimezone.Items.Count; i++) {
				lstDefaultTimezone.Items[i].Selected = false;
				if(lstDefaultTimezone.Items[i].Value.Equals(Settings.DefaultTimezone)) {
					lstDefaultTimezone.Items[i].Selected = true;
					break;
				}
			}

			chkUsersCanRegister.Checked = Settings.UsersCanRegister;
			for(int i = 0; i < lstAccountActivationMode.Items.Count; i++) {
				lstAccountActivationMode.Items[i].Selected = false;
				if(lstAccountActivationMode.Items[i].Value.Equals(Settings.AccountActivationMode)) {
					lstAccountActivationMode.Items[i].Selected = true;
					break;
				}
			}
			chkDisableCaptchaControl.Checked = Settings.DisableCaptchaControl;

			for(int i = 0; i < lstDiscussionPermissions.Items.Count; i++) {
				lstDiscussionPermissions.Items[i].Selected = false;
				if(lstDiscussionPermissions.Items[i].Value.ToLowerInvariant().Equals(Settings.DiscussionPermissions.ToLowerInvariant())) {
					lstDiscussionPermissions.Items[i].Selected = true;
					break;
				}
			}

			chkUsersCanCreateNewPages.Checked = Settings.UsersCanCreateNewPages;
			chkUsersCanCreateNewCategories.Checked = Settings.UsersCanCreateNewCategories;
			chkUsersCanManagePageCategories.Checked = Settings.UsersCanManagePageCategories;
			chkUsersCanViewFiles.Checked = Settings.UsersCanViewFiles;
			if(Settings.UsersCanViewFiles) {
				chkUsersCanUploadFiles.Checked = Settings.UsersCanUploadFiles;
				chkUsersCanDeleteFiles.Checked = Settings.UsersCanDeleteFiles;
				chkUsersCanUploadFiles.Enabled = true;
				chkUsersCanDeleteFiles.Enabled = true;
			}
			else {
				chkUsersCanUploadFiles.Checked = false;
				chkUsersCanDeleteFiles.Checked = false;
				chkUsersCanUploadFiles.Enabled = false;
				chkUsersCanDeleteFiles.Enabled = false;
			}
			chkPrivateAccess.Checked = Settings.PrivateAccess;
			if(Settings.PrivateAccess) {
				chkPublicAccess.Enabled = false;
				chkPublicAccess.Checked = false;
				chkFileManagementInPublicAccessAllowed.Enabled = false;
				chkFileManagementInPublicAccessAllowed.Checked = false;
			}
			else {
				if(Settings.PublicAccess) {
					chkPrivateAccess.Enabled = false;
					chkPrivateAccess.Checked = false;
					chkPublicAccess.Enabled = true;
					chkPublicAccess.Checked = true;
					chkFileManagementInPublicAccessAllowed.Enabled = true;
					chkFileManagementInPublicAccessAllowed.Checked = Settings.FileManagementInPublicAccessAllowed;
				}
				else {
					chkPrivateAccess.Enabled = true;
					chkPrivateAccess.Checked = false;
					chkPublicAccess.Enabled = true;
					chkPublicAccess.Checked = false;
					chkFileManagementInPublicAccessAllowed.Enabled = false;
					chkFileManagementInPublicAccessAllowed.Checked = false;
				}
			}

			chkDisableConcurrentEditing.Checked = Settings.DisableConcurrentEditing;

			txtAllowedFileTypes.Text = "";
			string[] aft = Settings.AllowedFileTypes;
			for(int i = 0; i < aft.Length; i++) {
				txtAllowedFileTypes.Text += aft[i];
				if(i != aft.Length - 1) txtAllowedFileTypes.Text += ", ";
			}

			chkScriptTagsAllowed.Checked = Settings.ScriptTagsAllowed;
			lstLoggingLevel.SelectedIndex = 3 - Settings.LoggingLevel;
			txtMaxLogSize.Text = Settings.MaxLogSize.ToString();
			chkConfigVisibleToAdmins.Checked = Settings.ConfigVisibleToAdmins;

			// Advanced Options
			chkDisableAutomaticVersionCheck.Checked = Settings.DisableAutomaticVersionCheck;
			txtMaxFileSize.Text = Settings.MaxFileSize.ToString();
			txtCacheSize.Text = Settings.CacheSize.ToString();
			txtCacheCutSize.Text = Settings.CacheCutSize.ToString();
			chkDisableCache.Checked = Settings.DisableCache;
			txtCacheSize.Enabled = !Settings.DisableCache;
			txtCacheCutSize.Enabled = !Settings.DisableCache;
			txtFileAccessTries.Text = Settings.FileAccessTries.ToString();
			txtFileAccessTryDelay.Text = Settings.FileAccessTryDelay.ToString();
			chkEnableViewStateCompression.Checked = Settings.EnableViewStateCompression;
			chkEnableHttpCompression.Checked = Settings.EnableHttpCompression;
			txtUsernameRegex.Text = Settings.UsernameRegex;
			txtPasswordRegex.Text = Settings.PasswordRegex;
		}

		public void PrintSystemStatus() {
			StringBuilder sb = new StringBuilder();
			sb.Append(Resources.Messages.OnlineUsers + ": <b>" + Users.OnlineUsers.ToString() + "</b><br />" + "\n");
			int inactive = 0;
			for(int i = 0; i < Users.Instance.AllUsers.Count; i++) {
				if(!Users.Instance.AllUsers[i].Active) inactive++;
			}
			sb.Append(Resources.Messages.UserCount + ": <b>" + Users.Instance.AllUsers.Count.ToString() + "</b> (" + inactive.ToString() + " " + Resources.Messages.InactiveUsers + ")<br />" + "\n");
			sb.Append(Resources.Messages.CachedPages + ": <b>" + Content.CacheUsage + "/" + Pages.Instance.AllPages.Count.ToString() + "</b><br />" + "\n");
			sb.Append(Resources.Messages.WikiVersion + ": <b>" + Settings.WikiVersion + "</b>" + "\n");
			if(!Page.IsPostBack) {
				sb.Append(CheckVersion());
			}
			sb.Append("<br />");
			sb.Append(Resources.Messages.ServerUptime + ": <b>" + Tools.TimeSpanToString(Tools.SystemUptime) + "</b> (" + Resources.Messages.MayBeInaccurate + ")");

			lblSystemStatusContent.Text = sb.ToString();
		}

		private string CheckVersion() {
			if(Settings.DisableAutomaticVersionCheck) return "";
			StringBuilder sb = new StringBuilder();
			sb.Append("(");
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.screwturn.eu/Version/Wiki/2.htm");
			try {
				HttpWebResponse res = (HttpWebResponse)req.GetResponse();
				StreamReader sr = new StreamReader(res.GetResponseStream());
				string ver = sr.ReadToEnd();
				sr.Close();
				string[] versions = ver.Split('|');
				bool upToDate = false;
				for(int i = 0; i < versions.Length; i++) {
					ver = versions[i];
					if(versions[i].Equals(Settings.WikiVersion)) {
						if(i == versions.Length - 1) upToDate = true;
						else upToDate = false;
						ver = versions[versions.Length - 1];
						break;
					}
				}
				if(!upToDate) {
					sb.Append(@"<span style=""color: #009900;"">" + Resources.Messages.NewVersionFound + ": <b>" + ver + "</b></span>");
				}
				else {
					sb.Append(@"<span style=""color: #009900;"">" + Resources.Messages.WikiUpToDate + "</span>");
				}
			}
			catch {
				sb.Append(@"<span style=""color: #FF0000;"">" + Resources.Messages.VersionCheckError + "</span>");
			}
			sb.Append(")");
			return sb.ToString();
		}

		public void PrintFileEditing() {
			StringBuilder sb = new StringBuilder();

			sb.Append("<ul>" + "\n");

			// Files that can be edited are specified in Settings.EditableFiles

			FileInfo fileInfo;

			fileInfo = new FileInfo(Settings.HeaderFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.HeaderFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.SidebarFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.SidebarFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.FooterFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.FooterFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.AccountActivationMessageFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.AccountActivationMessageFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.PasswordResetMessageFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.PasswordResetMessageFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.EditNoticeFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.EditNoticeFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.LoginNoticeFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.LoginNoticeFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>");

			fileInfo = new FileInfo(Settings.HtmlHeadFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.HtmlHeadFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>" + "\n");

			fileInfo = new FileInfo(Settings.PageHeaderFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.PageHeaderFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>");

			fileInfo = new FileInfo(Settings.PageFooterFile);
			sb.Append("<li>");
			sb.Append("<b>" + Resources.Messages.PageFooterFile + "</b> (" + Tools.BytesToString(fileInfo.Length) + @") - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=View"">" + Resources.Messages.View + @"</a> - <a href=""Edit.aspx?File=" + fileInfo.Name + @"&amp;Action=Edit"">" + Resources.Messages.Edit + @"</a>");
			sb.Append("</li>");

			sb.Append("</ul>" + "\n");

			lblFileEditingContent.Text = sb.ToString();
		}

		private void LoadSnippets() {
			lstSnippets.Items.Clear();
			for(int i = 0; i < Snippets.Instance.AllSnippets.Count; i++) {
				lstSnippets.Items.Add(new ListItem(Snippets.Instance.AllSnippets[i].Name + " [" + Snippets.Instance.AllSnippets[i].Provider.Information.Name + "]", Snippets.Instance.AllSnippets[i].Name));
			}
		}

		private void LoadCategories() {
			lstCategories.Items.Clear();
			lstMergeCategory.Items.Clear();
			lstMergeCategory.Enabled = false;
			for(int i = 0; i < Pages.Instance.AllCategories.Count; i++) {
				lstCategories.Items.Add(new ListItem(Pages.Instance.AllCategories[i].Name + " (" + Pages.Instance.AllCategories[i].Pages.Length.ToString() + ") [" + Pages.Instance.AllCategories[i].Provider.Information.Name + "]", Pages.Instance.AllCategories[i].Name));
			}
		}

		private void LoadNavPaths() {
			lstNavPaths.Items.Clear();
			for(int i = 0; i < NavigationPaths.Instance.Paths.Count; i++) {
				string pages = "";
				for(int k = 0; k < NavigationPaths.Instance.Paths[i].Pages.Count; k++) {
					pages += NavigationPaths.Instance.Paths[i].Pages[k];
					if(k != NavigationPaths.Instance.Paths[i].Pages.Count - 1) pages += ", ";
				}
				lstNavPaths.Items.Add(new ListItem(NavigationPaths.Instance.Paths[i].Name + " - " + pages + " [" + NavigationPaths.Instance.Paths[i].Provider.Information.Name + "]", NavigationPaths.Instance.Paths[i].Name));
			}
		}

		private void LoadProviders() {
			lstProviders.Items.Clear();
			lstDefaultPagesProvider.Items.Clear();
			lstCategoryProvider.Items.Clear();
			lstDefaultUsersProvider.Items.Clear();
			lstUserProvider.Items.Clear();
			lstNavPathProvider.Items.Clear();
			lstSnippetProvider.Items.Clear();
			lstPagesProviderFrom.Items.Clear();
			lstUsersProviderFrom.Items.Clear();

			string pd = Settings.DefaultPagesProvider;
			string ud = Settings.DefaultUsersProvider;

			int count = 0;

			lstPagesProviderFrom.Items.Add(new ListItem("", "-"));
			IPagesStorageProvider[] pgs = Collectors.PagesProviderCollector.AllProviders;
			for(int i = 0; i < pgs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[P] " + pgs[i].Information.Name, "[P]" + pgs[i].GetType().ToString()));
				lstPagesProviderFrom.Items.Add(new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString()));
				if(!pgs[i].ReadOnly) {
					lstDefaultPagesProvider.Items.Add(new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString()));
					lstCategoryProvider.Items.Add(new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString()));
					lstNavPathProvider.Items.Add(new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString()));
					lstSnippetProvider.Items.Add(new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString()));
					if(pgs[i].GetType().ToString().Equals(pd)) {
						lstDefaultPagesProvider.Items[count].Selected = true;
						lstCategoryProvider.Items[count].Selected = true;
						lstNavPathProvider.Items[count].Selected = true;
						lstSnippetProvider.Items[count].Selected = true;
					}
					count++;
				}
			}

			count = 0;

			lstUsersProviderFrom.Items.Add(new ListItem("", "-"));
			IUsersStorageProvider[] urs = Collectors.UsersProviderCollector.AllProviders;
			for(int i = 0; i < urs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[U] " + urs[i].Information.Name, "[U]" + urs[i].GetType().ToString()));
				lstUsersProviderFrom.Items.Add(new ListItem(urs[i].Information.Name, urs[i].GetType().ToString()));
				if(!urs[i].ReadOnly) {
					lstDefaultUsersProvider.Items.Add(new ListItem(urs[i].Information.Name, urs[i].GetType().ToString()));
					lstUserProvider.Items.Add(new ListItem(urs[i].Information.Name, urs[i].GetType().ToString()));
					if(urs[i].GetType().ToString().Equals(ud)) {
						lstDefaultUsersProvider.Items[count].Selected = true;
						lstUserProvider.Items[count].Selected = true;
					}
					count++;
				}
			}

			IFormatterProvider[] frs = Collectors.FormatterProviderCollector.AllProviders;
			for(int i = 0; i < frs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[F] " + frs[i].Information.Name, "[F]" + frs[i].GetType().ToString()));
			}

			pgs = Collectors.DisabledPagesProviderCollector.AllProviders;
			for(int i = 0; i < pgs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[P] " + pgs[i].Information.Name + " - " + Resources.Messages.Disabled, "[P]" + pgs[i].GetType().ToString()));
			}

			urs = Collectors.DisabledUsersProviderCollector.AllProviders;
			for(int i = 0; i < urs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[U] " + urs[i].Information.Name + " - " + Resources.Messages.Disabled, "[U]" + urs[i].GetType().ToString()));
			}

			frs = Collectors.DisabledFormatterProviderCollector.AllProviders;
			for(int i = 0; i < frs.Length; i++) {
				lstProviders.Items.Add(new ListItem("[F] " + frs[i].Information.Name + " - " + Resources.Messages.Disabled, "[F]" + frs[i].GetType().ToString()));
			}
		}

		private void LoadDlls() {
			string[] files = Directory.GetFiles(Settings.PluginsDirectory, "*.dll");
			lstDlls.Items.Clear();
			for(int i = 0; i < files.Length; i++) {
				lstDlls.Items.Add(new ListItem(Path.GetFileName(files[i]), Path.GetFileName(files[i])));
			}
		}

		private void LoadRegExp() {
			// Load RegExp's from Web.Config

			//User 
			rxvEmail.ValidationExpression = Settings.EmailRegex;
			rxvUserName.ValidationExpression = Settings.UsernameRegex;
			rxvPassword1.ValidationExpression = Settings.PasswordRegex;

			//Config
			rxvWikiTitle.ValidationExpression = Settings.WikiTitleRegex;
			rxvMainUrl.ValidationExpression = Settings.MainUrlRegex;
			rxvContactEmail.ValidationExpression = Settings.EmailRegex;
			rxvSenderEmail.ValidationExpression = Settings.EmailRegex;
			rxvSmtpServer.ValidationExpression = Settings.SmtpServerRegex;

		}

		private void LoadValidationLocalizations() {
			string image = @"<img src=""Images/InputError.png"" alt=""Error"" />";

			// User validators
			rfvUsername.ErrorMessage = Resources.Messages.RequiredField;
			rfvUsername.ToolTip = Resources.Messages.RequiredField;
			rfvUsername.Text = image;
			rfvEmail.ErrorMessage = Resources.Messages.RequiredField;
			rfvEmail.ToolTip = Resources.Messages.RequiredField;
			rfvEmail.Text = image;
			rfvPassword1.ErrorMessage = Resources.Messages.RequiredField;
			rfvPassword1.ToolTip = Resources.Messages.RequiredField;
			rfvPassword1.Text = image;
			rfvPassword2.ErrorMessage = Resources.Messages.RequiredField;
			rfvPassword2.ToolTip = Resources.Messages.RequiredField;
			rfvPassword2.Text = image;

			rxvUserName.ErrorMessage = Resources.Messages.InvalidUsername;
			rxvUserName.ToolTip = Resources.Messages.InvalidUsername;
			rxvUserName.Text = image;
			rxvEmail.ErrorMessage = Resources.Messages.InvalidEmail;
			rxvEmail.ToolTip = Resources.Messages.InvalidEmail;
			rxvEmail.Text = image;
			rxvPassword1.ErrorMessage = Resources.Messages.InvalidPassword;
			rxvPassword1.ToolTip = Resources.Messages.InvalidPassword;
			rxvPassword1.Text = image;

			cvUsername.ErrorMessage = Resources.Messages.UsernameAlreadyExists;
			cvUsername.ToolTip = Resources.Messages.UsernameAlreadyExists;
			cvUsername.Text = image;
			cvPassword1.ErrorMessage = Resources.Messages.PasswordsNotEqual;
			cvPassword1.ToolTip = Resources.Messages.PasswordsNotEqual;
			cvPassword1.Text = image;
			cvPassword2.ErrorMessage = Resources.Messages.PasswordsNotEqual;
			cvPassword2.ToolTip = Resources.Messages.PasswordsNotEqual;
			cvPassword2.Text = image;

			// Config Validators
			// General
			rfvWikiTitle.ErrorMessage = Resources.Messages.RequiredField;
			rfvWikiTitle.ToolTip = Resources.Messages.RequiredField;
			rfvWikiTitle.Text = image;
			rfvMainUrl.ErrorMessage = Resources.Messages.RequiredField;
			rfvMainUrl.ToolTip = Resources.Messages.RequiredField;
			rfvMainUrl.Text = image;
			rfvContactEmail.ErrorMessage = Resources.Messages.RequiredField;
			rfvContactEmail.ToolTip = Resources.Messages.RequiredField;
			rfvContactEmail.Text = image;
			rfvSenderEmail.ErrorMessage = Resources.Messages.RequiredField;
			rfvSenderEmail.ToolTip = Resources.Messages.RequiredField;
			rfvSenderEmail.Text = image;
			rfvSmtpServer.ErrorMessage = Resources.Messages.RequiredField;
			rfvSmtpServer.ToolTip = Resources.Messages.RequiredField;
			rfvSmtpServer.Text = image;
			cvSmtpAuth.ErrorMessage = Resources.Messages.UsernameIsRequired;
			cvSmtpAuth.ToolTip = Resources.Messages.UsernameIsRequired;
			cvSmtpAuth.Text = image;
			rvSmtpPort.ErrorMessage = Resources.Messages.InvalidPort;
			rvSmtpPort.ToolTip = Resources.Messages.InvalidPort;
			rvSmtpPort.Text = image;

			rxvWikiTitle.ErrorMessage = Resources.Messages.InvalidWikiTitle;
			rxvWikiTitle.ToolTip = Resources.Messages.InvalidWikiTitle;
			rxvWikiTitle.Text = image;
			rxvMainUrl.ErrorMessage = Resources.Messages.InvalidMainUrl;
			rxvMainUrl.ToolTip = Resources.Messages.InvalidMainUrl;
			rxvMainUrl.Text = image;
			rxvContactEmail.ErrorMessage = Resources.Messages.InvalidContactEmail;
			rxvContactEmail.ToolTip = Resources.Messages.InvalidContactEmail;
			rxvContactEmail.Text = image;
			rxvSenderEmail.ErrorMessage = Resources.Messages.InvalidSenderEmail;
			rxvSenderEmail.ToolTip = Resources.Messages.InvalidSenderEmail;
			rxvSenderEmail.Text = image;
			rxvSmtpServer.ErrorMessage = Resources.Messages.InvalidSmtpServer;
			rxvSmtpServer.ToolTip = Resources.Messages.InvalidSmtpServer;
			rxvSmtpServer.Text = image;
			//rvKeptBackupsNumber.ErrorMessage = Resources.Messages.InvalidBackupNumber;
			//rvKeptBackupsNumber.ToolTip = Resources.Messages.InvalidBackupNumber;
			//rvKeptBackupsNumber.Text = image;
			rfvDateTimeFormat.ErrorMessage = Resources.Messages.RequiredField;
			rfvDateTimeFormat.ToolTip = Resources.Messages.RequiredField;
			rfvDateTimeFormat.Text = image;
			cvDateTimeFormat.ErrorMessage = Resources.Messages.InvalidDateTimeFormat;
			cvDateTimeFormat.ToolTip = Resources.Messages.InvalidDateTimeFormat;
			cvDateTimeFormat.Text = image;

			rfvMaxLogSize.ErrorMessage = Resources.Messages.RequiredField;
			rfvMaxLogSize.ToolTip = Resources.Messages.RequiredField;
			rfvMaxLogSize.Text = image;
			rvMaxLogSize.ErrorMessage = Resources.Messages.InvalidMaxLogSize;
			rvMaxLogSize.ToolTip = Resources.Messages.InvalidMaxLogSize;
			rvMaxLogSize.Text = image;

			// Advanced
			rfvMaxFileSize.ErrorMessage = Resources.Messages.RequiredField;
			rfvMaxFileSize.ToolTip = Resources.Messages.RequiredField;
			rfvMaxFileSize.Text = image;
			rfvCacheSize.ErrorMessage = Resources.Messages.RequiredField;
			rfvCacheSize.ToolTip = Resources.Messages.RequiredField;
			rfvCacheSize.Text = image;
			rfvCacheCutSize.ErrorMessage = Resources.Messages.RequiredField;
			rfvCacheCutSize.ToolTip = Resources.Messages.RequiredField;
			rfvCacheCutSize.Text = image;
			rfvFileAccessTries.ErrorMessage = Resources.Messages.RequiredField;
			rfvFileAccessTries.ToolTip = Resources.Messages.RequiredField;
			rfvFileAccessTries.Text = image;
			rfvFileAccessTryDelay.ErrorMessage = Resources.Messages.RequiredField;
			rfvFileAccessTryDelay.ToolTip = Resources.Messages.RequiredField;
			rfvFileAccessTryDelay.Text = image;

			rvMaxFileSize.ErrorMessage = Resources.Messages.InvalidMaxFileSize;
			rvMaxFileSize.ToolTip = Resources.Messages.InvalidMaxFileSize;
			rvMaxFileSize.Text = image;
			rvCacheSize.ErrorMessage = Resources.Messages.InvalidCacheSize;
			rvCacheSize.ToolTip = Resources.Messages.InvalidCacheSize;
			rvCacheSize.Text = image;
			rvCacheCutSize.ErrorMessage = Resources.Messages.InvalidCacheCutSize;
			rvCacheCutSize.ToolTip = Resources.Messages.InvalidCacheCutSize;
			rvCacheCutSize.Text = image;
			rvFileAccessTries.ErrorMessage = Resources.Messages.InvalidFileAccessTries;
			rvFileAccessTries.ToolTip = Resources.Messages.InvalidFileAccessTries;
			rvFileAccessTries.Text = image;
			rvFileAccessTryDelay.ErrorMessage = Resources.Messages.InvalidFileAccessTryDelay;
			rvFileAccessTryDelay.ToolTip = Resources.Messages.InvalidFileAccessTryDelay;
			rvFileAccessTryDelay.Text = image;

			cmpvCacheCutSize.ErrorMessage = Resources.Messages.InvalidCacheCutSize;
			cmpvCacheCutSize.ToolTip = Resources.Messages.InvalidCacheCutSize;
			cmpvCacheCutSize.Text = image;
		}

		#endregion

		#region Users

		protected void chkViewUsers_CheckedChanged(object sender, EventArgs e) {
			LoadUsers();
		}

		protected void chkViewAdmins_CheckedChanged(object sender, EventArgs e) {
			LoadUsers();
		}

		protected void chkViewActive_CheckedChanged(object sender, EventArgs e) {
			LoadUsers();
		}

		protected void chkViewInactive_CheckedChanged(object sender, EventArgs e) {
			LoadUsers();
		}

		protected void btnDeleteUser_Click(object sender, EventArgs e) {
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Log.LogEntry("User removal requested for " + user.Username, EntryType.General, SessionFacade.Username);
			Users.Instance.RemoveUser(user);
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.UserDeleted;

			LoadUsers();
		}

		protected void btnDeactivateUser_Click(object sender, EventArgs e) {
			int index = lstUsers.SelectedIndex;
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Log.LogEntry("User deactivation requested for " + user.Username, EntryType.General, SessionFacade.Username);
			Users.Instance.SetActivationStatus(user, false);
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.UserDeactivated;

			LoadUsers();
			try {
				lstUsers.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnActivateUser_Click(object sender, EventArgs e) {
			int index = lstUsers.SelectedIndex;
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Log.LogEntry("User activation requested for " + user.Username, EntryType.General, SessionFacade.Username);
			Users.Instance.SetActivationStatus(user, true);
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.UserActivated;

			LoadUsers();
			try {
				lstUsers.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnPromoteUser_Click(object sender, EventArgs e) {
			int index = lstUsers.SelectedIndex;
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Log.LogEntry("User promotion requested for " + user.Username, EntryType.General, SessionFacade.Username);
			Users.Instance.SetAdministratorStatus(user, true);
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.UserPromoted;

			LoadUsers();
			try {
				lstUsers.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnDowngradeUser_Click(object sender, EventArgs e) {
			int index = lstUsers.SelectedIndex;
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Log.LogEntry("User downgrading requested for " + user.Username, EntryType.General, SessionFacade.Username);
			Users.Instance.SetAdministratorStatus(user, false);
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.AdminDowngraded;

			LoadUsers();
			try {
				lstUsers.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnSendMessage_Click(object sender, EventArgs e) {
			UserInfo user = Users.Instance.Find(lstUsers.SelectedValue);
			if(user == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			Response.Redirect("Message.aspx?Username=" + Tools.UrlEncode(user.Username));
		}

		protected void btnCreateNewAccount_Click(object sender, EventArgs e) {
			txtUsername.Enabled = true;
			mlvUsers.ActiveViewIndex = 1;
		}

		protected void btnCreateAccount_Click(object sender, EventArgs e) {
			lblCreateAccountResult.Text = "";

			if(!Page.IsValid) return;

			// Ready to save the user
			Log.LogEntry("Account creation requested for " + txtUsername.Text, EntryType.General, SessionFacade.Username);
			Users.Instance.AddUser(txtUsername.Text, txtPassword1.Text, txtEmail.Text, true, chkAdmin.Checked, Collectors.UsersProviderCollector.GetProvider(lstUserProvider.SelectedValue));

			ClearUserFields();

			mlvUsers.ActiveViewIndex = 0;
			LoadUsers();
		}

		protected void btnCancelAccountCreation_Click(object sender, EventArgs e) {
			ClearUserFields();

			mlvUsers.ActiveViewIndex = 0;
		}

		protected void lstUsers_SelectedIndexChanged(object sender, EventArgs e) {
			if(lstUsers.SelectedIndex != -1) {
				btnDeleteUser.Enabled = true;
				btnActivateUser.Enabled = true;
				btnDeactivateUser.Enabled = true;
				btnPromoteUser.Enabled = true;
				btnDowngradeUser.Enabled = true;
			}
			else {
				btnDeleteUser.Enabled = false;
				btnActivateUser.Enabled = false;
				btnDeactivateUser.Enabled = false;
				btnPromoteUser.Enabled = false;
				btnDowngradeUser.Enabled = false;
			}
		}

		private void ClearUserFields() {
			txtUsername.Text = "";
			txtPassword1.Text = "";
			txtPassword2.Text = "";
			txtEmail.Text = "";
			chkAdmin.Checked = false;

			txtUsername.Enabled = true;
			chkAdmin.Visible = true;
			lblPasswordChange.Visible = false;
			lblUserProvider.Visible = true;
			lstUserProvider.Visible = true;
			btnCreateAccount.Visible = true;
			btnModifyAccount.Visible = false;
		}

		protected void btnMassEmail_Click(object sender, EventArgs e) {
			btnSendMassEmail.Visible = true;
			btnCancelMassEmail.Visible = true;
			btnBack.Visible = false;
			lblMassEmailResult.Text = "";
			txtSubject.Text = "";
			txtBody.Text = "";
			mlvUsers.ActiveViewIndex = 2;
		}

		protected void btnSendMassEmail_Click(object sender, EventArgs e) {
			if(txtSubject.Text.Length == 0 || txtBody.Text.Length == 0) {
				lblMassEmailResult.CssClass = "resulterror";
				lblMassEmailResult.Text = Resources.Messages.SubjectBodyNeeded;
				return;
			}

			List<string> emails = new List<string>();
			bool users = chkSendUsers.Checked, admins = chkSendAdministrator.Checked;
			for(int i = 0; i < Users.Instance.AllUsers.Count; i++) {
				if(Users.Instance.AllUsers[i].Active &&
					((users && !Users.Instance.AllUsers[i].Admin) || (admins && Users.Instance.AllUsers[i].Admin))) {
					emails.Add(Users.Instance.AllUsers[i].Email);
				}
			}
			UserInfo user = Users.Instance.Find(SessionFacade.Username);
			if(user == null && SessionFacade.Username.Equals("admin")) user = new UserInfo("admin", Settings.ContactEmail, true, DateTime.Now, true, null);
			Log.LogEntry("Sending Mass Email to " + emails.Count.ToString() + " users", EntryType.General, SessionFacade.Username);
			EmailSender.SendMassEmail(emails.ToArray(), user.Email, txtSubject.Text, txtBody.Text, false);
			lblMassEmailResult.CssClass = "resultok";
			lblMassEmailResult.Text = Resources.Messages.MassEmailSent;
			btnSendMassEmail.Visible = false;
			btnCancelMassEmail.Visible = false;
			btnBack.Visible = true;
		}

		protected void btnCancelMassEmail_Click(object sender, EventArgs e) {
			mlvUsers.ActiveViewIndex = 0;
		}

		protected void btnBack_Click(object sender, EventArgs e) {
			mlvUsers.ActiveViewIndex = 0;
		}

		protected void btnEditAccount_Click(object sender, EventArgs e) {
			UserInfo u = Users.Instance.Find(lstUsers.SelectedValue);
			if(u == null) {
				lblUserResult.CssClass = "resulterror";
				lblUserResult.Text = Resources.Messages.UserNotFound;
				return;
			}
			txtUsername.Enabled = false;
			txtUsername.Text = u.Username;
			txtEmail.Text = u.Email;
			chkAdmin.Visible = false;
			lblPasswordChange.Visible = true;
			lblUserProvider.Visible = false;
			lstUserProvider.Visible = false;
			btnCreateAccount.Visible = false;
			btnModifyAccount.Visible = true;
			mlvUsers.ActiveViewIndex = 1;
		}

		protected void btnModifyAccount_Click(object sender, EventArgs e) {
			rfvEmail.Validate();
			rxvEmail.Validate();
			if(txtPassword1.Text.Length > 0 || txtPassword2.Text.Length > 0) {
				cvPassword1.Validate();
				cvPassword2.Validate();
			}
			if(!Page.IsValid) return;

			UserInfo u = Users.Instance.Find(txtUsername.Text);
			if(!u.Email.Equals(txtEmail.Text)) {
				Log.LogEntry("Email change requested for " + u.Username, EntryType.General, SessionFacade.Username);
				Users.Instance.ChangeEmail(u, txtEmail.Text);
			}
			if(txtPassword1.Text.Length > 0) {
				Log.LogEntry("Password change requested for " + u.Username, EntryType.General, SessionFacade.Username);
				Users.Instance.ChangePassword(u, txtPassword1.Text);
			}
			ClearUserFields();
			lblUserResult.CssClass = "resultok";
			lblUserResult.Text = Resources.Messages.UserAccountSaved;
			LoadUsers();
			mlvUsers.ActiveViewIndex = 0;
		}
		
		#endregion

		#region Pages

		protected void btnPagesPostback_Click(object sender, EventArgs e) {
			// No code needed
		}

		protected void chkViewLocked_CheckedChanged(object sender, EventArgs e) {
			LoadPages(true);
		}

		protected void chkViewNormal_CheckedChanged(object sender, EventArgs e) {
			LoadPages(true);
		}

		protected void chkViewPublic_CheckedChanged(object sender, EventArgs e) {
			LoadPages(true);
		}

		protected void btnGoToPage_Click(object sender, EventArgs e) {
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			Response.Redirect(page.Name + Settings.PageExtension);
		}

		protected void btnDeletePage_Click(object sender, EventArgs e) {
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			Log.LogEntry("Page deletion requested for " + page.Name, EntryType.General, SessionFacade.Username);
			Pages.Instance.DeletePage(page);
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.PageDeleted;

			txtPageName.Text = "";

			LoadPages(true);
		}

		protected void btnClearPageDiscussion_Click(object sender, EventArgs e) {
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			Log.LogEntry("Page Discussion deletion requested for " + page.Name, EntryType.General, SessionFacade.Username);
			Message[] messages = Pages.Instance.GetPageMessages(page);
			for(int i = 0; i < messages.Length; i++) {
				Pages.Instance.RemoveMessage(page, messages[i].ID, true);
			}
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.PageDiscussionCleared;
		}

		protected void btnSetPageStatus_Click(object sender, EventArgs e) {
			int index = lstPages.SelectedIndex;
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			switch(lstPageStatus.SelectedValue) {
				case "N":
					Log.LogEntry("Page Status change requested for " + page.Name + " (Normal)", EntryType.General, SessionFacade.Username);
					Pages.Instance.SetPageStatus(page, PageStatus.Normal);
					lblPageResult.CssClass = "resultok";
					lblPageResult.Text = Resources.Messages.PageSetNormal;
					break;
				case "P":
					Log.LogEntry("Page Status change requested for " + page.Name + " (Public)", EntryType.General, SessionFacade.Username);
					Pages.Instance.SetPageStatus(page, PageStatus.Public);
					lblPageResult.CssClass = "resultok";
					lblPageResult.Text = Resources.Messages.PageSetPublic;
					break;
				case "L":
					Log.LogEntry("Page Status change requested for " + page.Name + " (Locked)", EntryType.General, SessionFacade.Username);
					Pages.Instance.SetPageStatus(page, PageStatus.Locked);
					lblPageResult.CssClass = "resultok";
					lblPageResult.Text = Resources.Messages.PageSetLocked;
					break;
			}

			LoadPages(false);
			try {
				lstPages.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnDeleteAllBackups_Click(object sender, EventArgs e) {
			int index = lstPages.SelectedIndex;
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			Log.LogEntry("Page Backups (all) deletion requested for " + page.Name, EntryType.General, SessionFacade.Username);
			Pages.Instance.DeleteBackups(page);
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.PageBackupsDeleted;

			LoadPages(true);
			try {
				lstPages.SelectedIndex = index;
			}
			catch { }
		}

		protected void btnDeleteOlderBackups_Click(object sender, EventArgs e) {
			int index = lstPages.SelectedIndex;
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			string selectedBackup = lstPageBackups.SelectedValue;
			if(selectedBackup == null || selectedBackup.Length == 0 || selectedBackup.Equals(" --- ")) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PleaseSelectValidBackup;
				return;
			}
			int version = int.Parse(selectedBackup);

			Log.LogEntry("Page Backups (0-" + version.ToString() + ") deletion requested for " + page.Name, EntryType.General, SessionFacade.Username);
			Pages.Instance.DeleteBackups(page, version);
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.PageBackupsDeleted;

			LoadPages(true);
			try {
				lstPages.SelectedIndex = index;
				lstPages_SelectedIndexChanged(this, null); // Reload backups list
			}
			catch { }
		}

		protected void btnRollback_Click(object sender, EventArgs e) {
			int index = lstPages.SelectedIndex;
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			string selectedBackup = lstPageBackups.SelectedValue;
			if(selectedBackup == null || selectedBackup.Length == 0 || selectedBackup.Equals(" --- ")) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PleaseSelectValidBackup;
				return;
			}
			int version = int.Parse(selectedBackup);

			Log.LogEntry("Rollback to version " + version.ToString() + " requested for " + page.Name, EntryType.General, SessionFacade.Username);
			Pages.Instance.Rollback(page, version);
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.RollbackCompleted;

			LoadPages(true);
			try {
				lstPages.SelectedIndex = index;
				lstPages_SelectedIndexChanged(this, null);
			}
			catch { }
		}

		protected void btnRenamePage_Click(object sender, EventArgs e) {
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			if(!Pages.IsValidName(txtPageName.Text)) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.InvalidPageName;
				return;
			}
			if(Pages.Instance.FindPage(txtPageName.Text) != null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageAlreadyExists;
				return;
			}
			Log.LogEntry("Page Rename requested for " + page.Name + " to " + txtPageName.Text, EntryType.General, SessionFacade.Username);
			Pages.Instance.RenamePage(page, txtPageName.Text);
			lblPageResult.CssClass = "resultok";
			lblPageResult.Text = Resources.Messages.PageRenamed;

			LoadPages(true);

			for(int i = 0; i < lstPages.Items.Count; i++) {
				if(lstPages.Items[i].Text.StartsWith(txtPageName.Text + ",")) {
					lstPages.SelectedIndex = i;
					break;
				}
			}

			txtPageName.Text = "";
		}

		protected void lstPages_SelectedIndexChanged(object sender, EventArgs e) {
			PageInfo page = Pages.Instance.FindPage(lstPages.SelectedValue);
			if(page == null) {
				lblPageResult.CssClass = "resulterror";
				lblPageResult.Text = Resources.Messages.PageNotFound;
				return;
			}
			lstPageBackups.Items.Clear();
			List<int> backups = Pages.Instance.GetBackups(page);;
			backups.Reverse();
			for(int i = 0; i < backups.Count; i++) {
				lstPageBackups.Items.Add(
					new ListItem("Rev " + backups[i].ToString() + ", " +
					string.Format("{0:yyyy'/'MM'/'dd' 'HH':'mm':'ss}", Pages.Instance.GetBackupContent(page, backups[i]).LastModified),
					backups[i].ToString()));
			}
			if(lstPageBackups.Items.Count == 0) {
				lstPageBackups.Items.Add(new ListItem(" --- ", ""));
				btnDeleteAllBackups.Enabled = false;
				btnDeleteOlderBackups.Enabled = false;
				btnRollback.Enabled = false;
			}
			else {
				btnDeleteAllBackups.Enabled = true;
				btnDeleteOlderBackups.Enabled = true;
				btnRollback.Enabled = true;
			}
			if(lstPages.SelectedIndex != -1) {
				btnDeletePage.Enabled = true;
				btnClearPageDiscussion.Enabled = true;
				btnGoToPage.Enabled = true;
				btnSetPageStatus.Enabled = true;
				lstPageStatus.Enabled = true;
				btnRenamePage.Enabled = true;
				switch(page.Status) {
					case PageStatus.Normal:
						lstPageStatus.SelectedIndex = 0;
						break;
					case PageStatus.Public:
						lstPageStatus.SelectedIndex = 1;
						break;
					case PageStatus.Locked:
						lstPageStatus.SelectedIndex = 2;
						break;
				}
			}
			else {
				btnDeletePage.Enabled = false;
				btnSetPageStatus.Enabled = false;
				lstPageStatus.Enabled = false;
				btnRenamePage.Enabled = false;
			}

			// Populate txtPageName
			txtPageName.Text = page.Name;

			lblPageResult.Text = "";
		}

		#endregion

		#region Misc

		protected void chkViewMessages_CheckedChanged(object sender, EventArgs e) {
		}

		protected void chkViewWarnings_CheckedChanged(object sender, EventArgs e) {
		}

		protected void chkViewErrors_CheckedChanged(object sender, EventArgs e) {
		}

		protected void btnClearLog_Click(object sender, EventArgs e) {
			Log.ClearLog();
		}

		protected void btnComputeSpaceUsage_Click(object sender, EventArgs e) {
			FileInfo info = new FileInfo(Settings.LogFile);
			string txt = Resources.Messages.TotalDiskUsage + ": <b>" + Tools.BytesToString(Tools.DiskUsage(Settings.PublicDirectory)) + "</b>";
			txt += "<ul>";
			txt += "<li>" + Resources.Messages.PagesDiskUsage + ": <b>" + Tools.BytesToString(Tools.DiskUsage(Settings.PagesDirectory)) + "</b></li>";
			txt += "<li>" + Resources.Messages.FilesDiskUsage + ": <b>" + Tools.BytesToString(Tools.DiskUsage(Settings.UploadDirectory)) + "</b></li>";
			txt += "<li>" + Resources.Messages.LogDiskUsage + ": <b>" + Tools.BytesToString(info.Length) + "</b></li>";
			txt += "<li>" + Resources.Messages.TempDiskUsage + ": <b>" + Tools.BytesToString(Tools.DiskUsage(Settings.TempDirectory)) + "</b></li>";
			txt += "</ul><br />";
			lblDiskUsageResult.Text = txt;
		}

		protected void btnDownloadBackup_Click(object sender, EventArgs e) {
			Log.LogEntry("Backup ZIP requested", EntryType.General, SessionFacade.Username);
			Response.Redirect("Zip.aspx");
		}

		protected void btnClearTemp_Click(object sender, EventArgs e) {
			Log.LogEntry("TempDirectory cleanup requested", EntryType.General, SessionFacade.Username);
			string[] files = Directory.GetFiles(Settings.TempDirectory);
			for(int i = 0; i < files.Length; i++) {
				try {
					File.Delete(files[i]);
				}
				catch { }
			}
		}

		public void PrintStrings() {
			StringBuilder sb = new StringBuilder();
			sb.Append(@"<script type=""text/javascript"">" + "\n<!--\n");
			sb.Append(@"var __ConfirmOperationMessage = """ + Resources.Messages.ConfirmOperation + @""";");
			sb.Append("// -->\n</script>");
			lblStrings.Text = sb.ToString();
		}

		protected void btnClearCache_Click(object sender, EventArgs e) {
			Redirections.Instance.Clear();
			Content.PseudoCache.Clear();
			Content.InvalidateAll();
			PrintSystemStatus();
		}

		protected void btnRestartApp_Click(object sender, EventArgs e) {
			btnRestartAppConfirm.Enabled = true;
			btnRestartApp.Visible = false;
			btnRestartAppCancel.Visible = true;
		}

		protected void btnRestartAppConfirm_Click(object sender, EventArgs e) {
			Log.LogEntry("WebApp shutdown requested", EntryType.General, SessionFacade.Username);
			Response.Clear();
			Response.Write(@"Web Application has been shut down, please go to the <a href=""Default.aspx"">home page</a>." + "\n\n");
			Response.Flush();
			Response.Close();
			Log.LogEntry("Executing WebApp shutdown", EntryType.General, "SYSTEM");
			HttpRuntime.UnloadAppDomain();
		}

		protected void btnRestartAppCancel_Click(object sender, EventArgs e) {
			btnRestartAppConfirm.Enabled = false;
			btnRestartApp.Visible = true;
			btnRestartAppCancel.Visible = false;
		}

		public void PrintDateTimeFormats() {
			StringBuilder sb = new StringBuilder();
			DateTime test = DateTime.Now;
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('ddd, dd MMM yyyy HH\':\'mm');"">" + test.ToString("ddd, dd MMM yyyy HH':'mm") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('dddd, dd MMMM yyyy HH\':\'mm');"">" + test.ToString("dddd, dd MMMM yyyy HH':'mm") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('yyyy\'/\'MM\'/\'dd\' \'HH\':\'mm');"">" + test.ToString("yyyy'/'MM'/'dd' 'HH':'mm") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('MM\'/\'dd\'/\'yyyy\' \'HH\':\'mm');"">" + test.ToString("MM'/'dd'/'yyyy' 'HH':'mm") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('dd\'/\'MM\'/\'yyyy\' \'HH\':\'mm');"">" + test.ToString("dd'/'MM'/'yyyy' 'HH':'mm") + "</a>");

			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('ddd, dd MMM yyyy hh\':\'mm\' \'tt');"">" + test.ToString("ddd, dd MMM yyyy hh':'mm' 'tt") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('dddd, dd MMMM yyyy hh\':\'mm\' \'tt');"">" + test.ToString("dddd, dd MMMM yyyy hh':'mm' 'tt") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('yyyy\'/\'MM\'/\'dd\' \'hh\':\'mm\' \'tt');"">" + test.ToString("yyyy'/'MM'/'dd' 'hh':'mm' 'tt") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('MM\'/\'dd\'/\'yyyy\' \'hh\':\'mm\' \'tt');"">" + test.ToString("MM'/'dd'/'yyyy' 'hh':'mm' 'tt") + "</a>");
			sb.Append(@"<a href=""#"" class=""datepicklink"" onclick=""javascript:return __SetDateFormat('dd\'/\'MM\'/\'yyyy\' \'hh\':\'mm\' \'tt');"">" + test.ToString("dd'/'MM'/'yyyy' 'hh':'mm' 'tt") + "</a>");

			lblDateTimeFormatsContent.Text = sb.ToString();
		}

		#endregion

		#region Config

		protected void btnSave_Click(object sender, EventArgs e) {
			lblConfigResult.Text = "";
			lblConfigResult.CssClass = "";

			if(!Page.IsValid) return;

			// Save parameters
			Settings.WikiTitle = txtWikiTitle.Text;
			Settings.MainUrl = txtMainUrl.Text;
			Settings.Theme = lstTheme.SelectedValue;
			Settings.ContactEmail = txtContactEmail.Text;
			Settings.SenderEmail = txtSenderEmail.Text;
			Settings.SmtpServer = txtSmtpServer.Text;
			Settings.SmtpUsername = txtSmtpUsername.Text;
			Settings.SmtpPassword = txtSmtpPassword.Text;
			Settings.SmtpPort = txtSmtpPort.Text.Length > 0 ? int.Parse(txtSmtpPort.Text) : -1;
			Settings.SmtpSsl = chkSmtpSsl.Checked;
			Settings.DefaultPage = lstDefaultPage.SelectedValue;
			Settings.EnableDoubleClickEditing = chkEnableDoubleClickEditing.Checked;
			Settings.DisableBreadcrumbsTrail = chkDisableBreadcrumbsTrail.Checked;
			Settings.ProcessSingleLineBreaks = chkProcessSingleLineBreaks.Checked;

			// This feature is currently DISABLED
			/*if(txtKeptBackupsNumber.Text.Length > 0) {
				Settings.KeptBackupNumber = int.Parse(txtKeptBackupsNumber.Text);
			}
			else Settings.KeptBackupNumber = -1;*/

			Settings.DateTimeFormat = txtDateTimeFormat.Text;
			Settings.DefaultLanguage = lstDefaultLanguage.SelectedValue;
			Settings.DefaultTimezone = lstDefaultTimezone.SelectedValue;
			Settings.UsersCanRegister = chkUsersCanRegister.Checked;
			Settings.AccountActivationMode = lstAccountActivationMode.SelectedValue;
			Settings.DisableCaptchaControl = chkDisableCaptchaControl.Checked;
			Settings.DiscussionPermissions = lstDiscussionPermissions.SelectedValue;
			Settings.UsersCanCreateNewPages = chkUsersCanCreateNewPages.Checked;
			Settings.UsersCanCreateNewCategories = chkUsersCanCreateNewCategories.Checked;
			Settings.UsersCanManagePageCategories = chkUsersCanManagePageCategories.Checked;
			Settings.UsersCanViewFiles = chkUsersCanViewFiles.Checked;
			if(chkUsersCanViewFiles.Checked) {
				Settings.UsersCanUploadFiles = chkUsersCanUploadFiles.Checked;
				Settings.UsersCanDeleteFiles = chkUsersCanDeleteFiles.Checked;
			}
			else {
				Settings.UsersCanUploadFiles = false;
				Settings.UsersCanDeleteFiles = false;
			}
			Settings.PrivateAccess = chkPrivateAccess.Checked;
			if(chkPrivateAccess.Checked) {
				Settings.PublicAccess = false;
				Settings.FileManagementInPublicAccessAllowed = false;
			}
			else {
				Settings.PublicAccess = chkPublicAccess.Checked;
				if(chkPublicAccess.Checked)
					Settings.FileManagementInPublicAccessAllowed = chkFileManagementInPublicAccessAllowed.Checked;
				else Settings.FileManagementInPublicAccessAllowed = false;
			}
			Settings.DisableConcurrentEditing = chkDisableConcurrentEditing.Checked;
			Settings.AllowedFileTypes = txtAllowedFileTypes.Text.Replace(" ", "").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			Settings.ScriptTagsAllowed = chkScriptTagsAllowed.Checked;
			Settings.LoggingLevel = int.Parse(lstLoggingLevel.SelectedValue);
			Settings.MaxLogSize = int.Parse(txtMaxLogSize.Text);
			Settings.ConfigVisibleToAdmins = chkConfigVisibleToAdmins.Checked;
			Settings.DisableAutomaticVersionCheck = chkDisableAutomaticVersionCheck.Checked;
			Settings.MaxFileSize = int.Parse(txtMaxFileSize.Text);
			Settings.DisableCache = chkDisableCache.Checked;
			Settings.CacheSize = int.Parse(txtCacheSize.Text);
			Settings.CacheCutSize = int.Parse(txtCacheCutSize.Text);
			Settings.FileAccessTries = int.Parse(txtFileAccessTries.Text);
			Settings.FileAccessTryDelay = int.Parse(txtFileAccessTryDelay.Text);
			Settings.EnableViewStateCompression = chkEnableViewStateCompression.Checked;
			Settings.EnableHttpCompression = chkEnableHttpCompression.Checked;
			Settings.UsernameRegex = txtUsernameRegex.Text;
			Settings.PasswordRegex = txtPasswordRegex.Text;

			// Dump Config
			Log.LogEntry("Config dump requested", EntryType.General, SessionFacade.Username);
			Settings.DumpConfig();

			// Clear invalid cache entries
			Content.PseudoCache.Clear();
			Content.InvalidateAll();

			LoadConfig();

			lblConfigResult.CssClass = "resultok";
			lblConfigResult.Text = Resources.Messages.ConfigSaved;
		}

		protected void btnCancel_Click(object sender, EventArgs e) {
			LoadConfig();
			lblConfigResult.CssClass = "resultok";
			lblConfigResult.Text = Resources.Messages.ConfigValuesReset;
		}

		protected void chkPrivateAccess_CheckedChanged(object sender, EventArgs e) {
			if(chkPrivateAccess.Checked) {
				chkPublicAccess.Enabled = false;
				chkPublicAccess.Checked = false;
				chkFileManagementInPublicAccessAllowed.Enabled = false;
				chkFileManagementInPublicAccessAllowed.Checked = false;
			}
			else {
				chkPublicAccess.Enabled = true;
				chkFileManagementInPublicAccessAllowed.Enabled = false;
			}
		}
		protected void chkPublicAccess_CheckedChanged(object sender, EventArgs e) {
			if(chkPublicAccess.Checked) {
				chkFileManagementInPublicAccessAllowed.Enabled = true;
				chkPrivateAccess.Enabled = false;
				chkPrivateAccess.Checked = false;
			}
			else {
				chkFileManagementInPublicAccessAllowed.Enabled = false;
				chkFileManagementInPublicAccessAllowed.Checked = false;
				chkPrivateAccess.Enabled = true;
			}
		}

		protected void chkUsersCanViewFiles_CheckedChanged(object sender, EventArgs e) {
			if(!chkUsersCanViewFiles.Checked) {
				chkUsersCanUploadFiles.Checked = false;
				chkUsersCanDeleteFiles.Checked = false;
				chkUsersCanUploadFiles.Enabled = false;
				chkUsersCanDeleteFiles.Enabled = false;
			}
			else {
				chkUsersCanUploadFiles.Checked = false;
				chkUsersCanDeleteFiles.Checked = false;
				chkUsersCanUploadFiles.Enabled = true;
				chkUsersCanDeleteFiles.Enabled = true;
			}
		}

		protected void chkDisableCache_CheckedChanged(object sender, EventArgs e) {
			if(chkDisableCache.Checked) {
				txtCacheSize.Enabled = false;
				txtCacheCutSize.Enabled = false;
			}
			else {
				txtCacheSize.Enabled = true;
				txtCacheCutSize.Enabled = true;
			}
		}

		#endregion

		#region Tabs Buttons

		protected void btnSelectUsersAdmins_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 0;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectPages_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 1;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectFiles_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 2;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectLog_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 3;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectDisk_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 4;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectConfig_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 5;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectDataBackup_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 6;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectSnippets_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 7;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectCategories_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 8;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectAdminHome_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 9;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}
		protected void btnSelectNavPaths_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 10;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}

		protected void btnSelectProviders_Click(object sender, EventArgs e) {
			mlvAdmin.ActiveViewIndex = 11;
			SessionFacade.AdminView = mlvAdmin.ActiveViewIndex;
			SetupButtons();
		}

		private void SetupButtons() {
			btnSelectUsersAdmins.CssClass = "tab";
			btnSelectPages.CssClass = "tab";
			btnSelectFiles.CssClass = "tab";
			btnSelectLog.CssClass = "tab";
			btnSelectDisk.CssClass = "tab";
			btnSelectConfig.CssClass = "tab";
			btnSelectDataBackup.CssClass = "tab";
			btnSelectSnippets.CssClass = "tab";
			btnSelectCategories.CssClass = "tab";
			btnSelectAdminHome.CssClass = "tab";
			btnSelectNavPaths.CssClass = "tab";
			btnSelectProviders.CssClass = "tab";

			switch(SessionFacade.AdminView) {
				case 0:
					SetButton(btnSelectUsersAdmins);
					break;
				case 1:
					SetButton(btnSelectPages);
					break;
				case 2:
					SetButton(btnSelectFiles);
					break;
				case 3:
					SetButton(btnSelectLog);
					break;
				case 4:
					SetButton(btnSelectDisk);
					break;
				case 5:
					SetButton(btnSelectConfig);
					break;
				case 6:
					SetButton(btnSelectDataBackup);
					break;
				case 7:
					SetButton(btnSelectSnippets);
					break;
				case 8:
					SetButton(btnSelectCategories);
					break;
				case 9:
					SetButton(btnSelectAdminHome);
					break;
				case 10:
					SetButton(btnSelectNavPaths);
					break;
				case 11:
					SetButton(btnSelectProviders);
					break;
			}
		}

		private void SetButton(Button btn) {
			btn.CssClass = "tabselected";
		}

		#endregion

		#region Snippets

		protected void btnDeleteSnippet_Click(object sender, EventArgs e) {
			Snippet s = Snippets.Instance.Find(lstSnippets.SelectedValue);
			
			if(s == null) {
				lblSnippetResult.CssClass = "resulterror";
				lblSnippetResult.Text = Resources.Messages.SnippetNotFound;
				LoadSnippets();
				return;
			}

			Log.LogEntry("Snippet deletion requested for " + s.Name, EntryType.General, SessionFacade.Username);
			Snippets.Instance.RemoveSnippet(s);
			lblSnippetResult.CssClass = "resultok";
			lblSnippetResult.Text = Resources.Messages.SnippetDeleted;
			LoadSnippets();
			Content.InvalidateAll();
			Content.PseudoCache.Clear();
		}

		protected void btnEditSnippet_Click(object sender, EventArgs e) {
			Snippet s = Snippets.Instance.Find(lstSnippets.SelectedValue);
			if(s == null) {
				lblSnippetResult.CssClass = "resulterror";
				lblSnippetResult.Text = Resources.Messages.SnippetNotFound;
				return;
			}
			mlvSnippets.ActiveViewIndex = 1;
			txtSnippetName.Text = s.Name;
			txtSnippetName.Enabled = false;
			txtSnippetName.Style.Clear();
			txtSnippetContent.Text = s.Content;
			lblSnippetProvider.Visible = false;
			lstSnippetProvider.Visible = false;
			lblSaveSnippetResult.Text = "";
		}

		protected void btnNewSnippet_Click(object sender, EventArgs e) {
			mlvSnippets.ActiveViewIndex = 1;
			txtSnippetName.Text = "";
			txtSnippetName.Enabled = true;
			txtSnippetName.Style.Clear();
			txtSnippetContent.Text = "";
			lblSnippetProvider.Visible = true;
			lstSnippetProvider.Visible = true;
			lblSaveSnippetResult.Text = "";
		}

		protected void btnSaveSnippet_Click(object sender, EventArgs e) {
			if(txtSnippetName.Enabled) {
				if(txtSnippetName.Text.Replace(" ", "").Length == 0 || !Pages.IsValidName(txtSnippetName.Text)) {
					lblSaveSnippetResult.CssClass = "resulterror";
					lblSaveSnippetResult.Text = Resources.Messages.InvalidSnippetName;
					return;
				}
				for(int i = 0; i < Snippets.Instance.AllSnippets.Count; i++) {
					if(Snippets.Instance.AllSnippets[i].Name.ToLower(CultureInfo.CurrentCulture).Equals(txtSnippetName.Text.ToLower(CultureInfo.CurrentCulture))) {
						lblSaveSnippetResult.CssClass = "resulterror";
						lblSaveSnippetResult.Text = Resources.Messages.SnippetAlreadyExists;
						return;
					}
				}
				Log.LogEntry("Snippet creation requested for " + txtSnippetName.Text, EntryType.General, SessionFacade.Username);
				Snippets.Instance.AddSnippet(txtSnippetName.Text, txtSnippetContent.Text, Collectors.PagesProviderCollector.GetProvider(lstSnippetProvider.SelectedValue));
			}
			else {
				Log.LogEntry("Snippet update requested for " + txtSnippetName.Text, EntryType.General, SessionFacade.Username);
				Snippets.Instance.ModifySnippet(Snippets.Instance.Find(txtSnippetName.Text), txtSnippetContent.Text);
			}
			lblSnippetResult.CssClass = "resultok";
			lblSnippetResult.Text = Resources.Messages.SnippetSaved;
			mlvSnippets.ActiveViewIndex = 0;
			LoadSnippets();
			Content.InvalidateAll();
			Content.PseudoCache.Clear();
		}

		protected void btnCancelSnippet_Click(object sender, EventArgs e) {
			mlvSnippets.ActiveViewIndex = 0;
			lblSnippetResult.Text = "";
		}

		#endregion

		#region Categories

		protected void lstCategories_SelectedIndexChanged(object sender, EventArgs e) {
			lstMergeCategory.Items.Clear();
			CategoryInfo selected = Pages.Instance.FindCategory(lstCategories.SelectedValue);
			if(selected != null) {
				lstMergeCategory.Enabled = true;
				txtCategoryName.Text = selected.Name;
				CategoryInfo[] cats = Pages.Instance.GetMatchingCategories(selected);
				for(int i = 0; i < cats.Length; i++) {
					lstMergeCategory.Items.Add(new ListItem(cats[i].Name, cats[i].Name));
				}
			}
			else lstMergeCategory.Enabled = false;
		}

		protected void btnDeleteCategory_Click(object sender, EventArgs e) {
			string cat = lstCategories.SelectedValue;
			if(Pages.Instance.FindCategory(cat) == null) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.CategoryNotFound;
				return;
			}
			Log.LogEntry("Category removal requested for " + cat, EntryType.General, SessionFacade.Username);
			Pages.Instance.RemoveCategory(Pages.Instance.FindCategory(cat));
			LoadCategories();
			lblCategoryResult.CssClass = "resultok";
			lblCategoryResult.Text = Resources.Messages.CategoryDeleted;
		}

		protected void btnRenameCategory_Click(object sender, EventArgs e) {
			string cat = lstCategories.SelectedValue;
			if(Pages.Instance.FindCategory(cat) == null) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.CategoryNotFound;
				return;
			}
			if(!Pages.IsValidName(txtCategoryName.Text)) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.InvalidCategoryName;
				return;
			}
			if(Pages.Instance.FindCategory(txtCategoryName.Text) != null) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.InvalidCategoryName;
				return;
			}
			Log.LogEntry("Category rename requested for " + cat + " (" + txtCategoryName.Text + ")", EntryType.General, SessionFacade.Username);
			Pages.Instance.RenameCategory(Pages.Instance.FindCategory(cat), txtCategoryName.Text);
			LoadCategories();
			txtCategoryName.Text = "";
			lblCategoryResult.CssClass = "resultok";
			lblCategoryResult.Text = Resources.Messages.CategoryRenamed;
		}

		protected void btnNewCategory_Click(object sender, EventArgs e) {
			if(!Pages.IsValidName(txtCategoryName.Text)) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.InvalidCategoryName;
				return;
			}
			Log.LogEntry("Category creation requested for " + txtCategoryName.Text, EntryType.General, SessionFacade.Username);
			Pages.Instance.CreateCategory(txtCategoryName.Text, Collectors.PagesProviderCollector.GetProvider(lstCategoryProvider.SelectedValue));
			LoadCategories();
			txtCategoryName.Text = "";
			lblCategoryResult.CssClass = "resultok";
			lblCategoryResult.Text = Resources.Messages.CategorySaved;
		}

		protected void btnMergeCategory_Click(object sender, EventArgs e) {
			CategoryInfo source = Pages.Instance.FindCategory(lstCategories.SelectedValue);
			if(source == null) {
				lblCategoryResult.CssClass = "resulterror";
				lblCategoryResult.Text = Resources.Messages.CategoryNotFound;
				return;
			}
			Log.LogEntry("Categories Merging requested for " + source.Name + " into " + lstMergeCategory.SelectedValue, EntryType.General, SessionFacade.Username);
			Pages.Instance.MergeCategories(source, Pages.Instance.FindCategory(lstMergeCategory.SelectedValue));
			LoadCategories();
			lblCategoryResult.CssClass = "resultok";
			lblCategoryResult.Text = Resources.Messages.CategoriesMerged;
		}

		#endregion

		#region Nav Paths

		protected void btnDeleteNavPath_Click(object sender, EventArgs e) {
			if(lstNavPaths.SelectedIndex == -1) {
				lblNavPathResult.CssClass = "resulterror";
				lblNavPathResult.Text =Resources.Messages.NavPathNotFound;
				return;
			}
			Log.LogEntry("NavPath removal requested for " + lstNavPaths.SelectedValue, EntryType.General, SessionFacade.Username);
			NavigationPaths.Instance.RemovePath(lstNavPaths.SelectedValue);
			lblNavPathResult.CssClass = "resultok";
			lblNavPathResult.Text = Resources.Messages.NavPathDeleted;
			LoadNavPaths();
		}

		protected void btnEditNavPath_Click(object sender, EventArgs e) {
			if(lstNavPaths.SelectedIndex == -1) {
				lblNavPathResult.CssClass = "resulterror";
				lblNavPathResult.Text = Resources.Messages.NavPathNotFound;
				return;
			}
			NavigationPath p = NavigationPaths.Instance.Find(lstNavPaths.SelectedValue);
			txtNavPathName.Text = p.Name;
			txtNavPathName.Enabled = false;
			string s = "";
			for(int i = 0; i < p.Pages.Count; i++) {
				s += p.Pages[i];
				if(i != p.Pages.Count - 1) s += ", ";
			}
			txtNavPath.Text = s;
			lblEditNavPathResult.Text = "";
			lblNavPathProvider.Visible = false;
			lstNavPathProvider.Visible = false;
			mlvNavPaths.ActiveViewIndex = 1;
		}

		protected void btnNewNavPath_Click(object sender, EventArgs e) {
			txtNavPathName.Text = "";
			txtNavPathName.Enabled = true;
			txtNavPath.Text = "";
			lblEditNavPathResult.Text = "";
			lblNavPathProvider.Visible = true;
			lstNavPathProvider.Visible = true;
			mlvNavPaths.ActiveViewIndex = 1;
		}

		protected void btnSaveNavPath_Click(object sender, EventArgs e) {
			txtNavPath.Text = txtNavPath.Text.Replace("\r", "").Replace("\n", "");
			if(!Pages.IsValidName(txtNavPathName.Text)) {
				lblEditNavPathResult.CssClass = "resulterror";
				lblEditNavPathResult.Text = Resources.Messages.InvalidNavPathName;
				return;
			}
			if(txtNavPathName.Enabled) {
				if(NavigationPaths.Instance.Exists(txtNavPathName.Text)) {
					lblEditNavPathResult.CssClass = "resulterror";
					lblEditNavPathResult.Text = Resources.Messages.NavPathAlreadyExists;
					return;
				}
			}

			string[] pages = txtNavPath.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			if(pages.Length < 2) {
				lblEditNavPathResult.CssClass = "resulterror";
				lblEditNavPathResult.Text = Resources.Messages.InvalidNavPath;
				return;
			}

			IPagesStorageProvider prov = null;
			if(lstNavPathProvider.Visible) prov = Collectors.PagesProviderCollector.GetProvider(lstNavPathProvider.SelectedValue);
			else prov = NavigationPaths.Instance.Find(txtNavPathName.Text).Provider;
			PageInfo[] infos = new PageInfo[pages.Length];
			for(int i = 0; i < pages.Length; i++) {
				pages[i] = pages[i].Trim();
				if(Pages.Instance.FindPage(pages[i], prov) == null) {
					lblEditNavPathResult.CssClass = "resulterror";
					lblEditNavPathResult.Text = Resources.Messages.PageDoesNotExistInProvider.Replace("##PAGENAME##", "<b>" + pages[i] + "</b>");
					return;
				}
				infos[i] = Pages.Instance.FindPage(pages[i]);
			}

			if(txtNavPathName.Enabled) {
				Log.LogEntry("NavPath creation requested for " + txtNavPath.Text, EntryType.General, SessionFacade.Username);
				NavigationPaths.Instance.AddPath(txtNavPathName.Text, new List<PageInfo>(infos), Collectors.PagesProviderCollector.GetProvider(lstNavPathProvider.SelectedValue));
			}
			else {
				Log.LogEntry("NavPath update requested for " + txtNavPath.Text, EntryType.General, SessionFacade.Username);
				NavigationPaths.Instance.ModifyPath(txtNavPathName.Text, new List<PageInfo>(infos));
			}
			LoadNavPaths();
			lblNavPathResult.CssClass = "resultok";
			lblNavPathResult.Text = Resources.Messages.NavPathSaved;
			mlvNavPaths.ActiveViewIndex = 0;
		}

		protected void btnCancelNavPath_Click(object sender, EventArgs e) {
			lblNavPathResult.Text = "";
			mlvNavPaths.ActiveViewIndex = 0;
		}

		#endregion

		#region Providers

		protected void btnSaveDefaultProviders_Click(object sender, EventArgs e) {
			Settings.DefaultPagesProvider = lstDefaultPagesProvider.SelectedValue;
			Settings.DefaultUsersProvider = lstDefaultUsersProvider.SelectedValue;
			Settings.DumpConfig();
		}

		protected void btnCancelDefaultProviders_Click(object sender, EventArgs e) {
			LoadProviders();
		}

		protected void btnConfigureProvider_Click(object sender, EventArgs e) {
			lblProviderResult.Text = "";
			lblProviderResult.CssClass = "";

			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			string config = "";

			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.UsersProviderCollector.GetProvider(name);
					if(u == null) u = Collectors.DisabledUsersProviderCollector.GetProvider(name);
					if(u == null) throw new Exception();
					config = ProviderLoader.LoadConfiguration(u.GetType().ToString());
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.PagesProviderCollector.GetProvider(name);
					if(p == null) p = Collectors.DisabledPagesProviderCollector.GetProvider(name);
					if(p == null) throw new Exception();
					config = ProviderLoader.LoadConfiguration(p.GetType().ToString());
					break;
				case "[F]":
					IFormatterProvider f = Collectors.FormatterProviderCollector.GetProvider(name);
					if(f == null) f = Collectors.DisabledFormatterProviderCollector.GetProvider(name);
					if(f == null) throw new Exception();
					config = ProviderLoader.LoadConfiguration(f.GetType().ToString());
					break;
				default:
					throw new Exception();
			}

			txtProviderConfiguration.Text = config;
			pnlProviderConfiguration.Visible = true;
			lstProviders.Enabled = false;
			btnConfigureProvider.Enabled = false;
			btnEnableProvider.Enabled = false;
			btnDisableProvider.Enabled = false;
			pnlPoviderInfo.Visible = false;

		}

		protected void btnSaveProviderConfiguration_Click(object sender, EventArgs e) {
			lblProviderResult.Text = "";

			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			bool err = false;

			bool disabled = false;
			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.UsersProviderCollector.GetProvider(name);
					if(u == null) {
						u = Collectors.DisabledUsersProviderCollector.GetProvider(name);
						disabled = true;
					}
					if(u == null) throw new Exception();
					try {
						u.Init(Host.Instance, txtProviderConfiguration.Text);
						ProviderLoader.SaveConfiguration(u.GetType().ToString(), txtProviderConfiguration.Text);
						if(!disabled) Users.Instance.ReloadFrom(u);
						LoadUsers();
					}
					catch(InvalidConfigurationException) {
						err = true;
					}
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.PagesProviderCollector.GetProvider(name);
					if(p == null) {
						p = Collectors.DisabledPagesProviderCollector.GetProvider(name);
						disabled = true;
					}
					if(p == null) throw new Exception();
					try {
						p.Init(Host.Instance, txtProviderConfiguration.Text);
						ProviderLoader.SaveConfiguration(p.GetType().ToString(), txtProviderConfiguration.Text);
						if(!disabled) {
							Content.InvalidateAll();
							Content.PseudoCache.Clear();
							Pages.Instance.ReloadFrom(p);
						}
						LoadPages(true);
						LoadCategories();
						LoadSnippets();
						LoadNavPaths();
					}
					catch(InvalidConfigurationException) {
						err = true;
					}
					break;
				case "[F]":
					IFormatterProvider f = Collectors.FormatterProviderCollector.GetProvider(name);
					if(f == null) {
						f = Collectors.DisabledFormatterProviderCollector.GetProvider(name);
						disabled = true;
					}
					if(f == null) throw new Exception();
					try {
						f.Init(Host.Instance, txtProviderConfiguration.Text);
						ProviderLoader.SaveConfiguration(f.GetType().ToString(), txtProviderConfiguration.Text);
						if(!disabled) {
							Content.InvalidateAll();
							Content.PseudoCache.Clear();
						}
					}
					catch(InvalidConfigurationException) {
						err = true;
					}
					break;
				default:
					throw new Exception();
			}

			if(err) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderRefusedConfiguration;
			}
			else {
				lblProviderResult.CssClass = "resultok";
				lblProviderResult.Text = Resources.Messages.ProviderConfigurationSaved;
				lblProviderConfiguration.Text = txtProviderConfiguration.Text;
				pnlProviderConfiguration.Visible = false;
				lstProviders.Enabled = true;
				btnConfigureProvider.Enabled = true;
				btnEnableProvider.Enabled = true;
				btnDisableProvider.Enabled = true;
				pnlPoviderInfo.Visible = true;
				lstProviders_SelectedIndexChanged(sender, e);
			}
		}

		protected void btnCancelProviderConfiguration_Click(object sender, EventArgs e) {
			pnlProviderConfiguration.Visible = false;
			lstProviders.Enabled = true;
			btnConfigureProvider.Enabled = true;
			btnEnableProvider.Enabled = true;
			btnDisableProvider.Enabled = true;
			pnlPoviderInfo.Visible = true;
		}

		protected void btnEnableProvider_Click(object sender, EventArgs e) {
			lblProviderResult.Text = "";

			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			bool err = false;

			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.DisabledUsersProviderCollector.GetProvider(name);
					if(u != null) {
						try {
							u.Init(Host.Instance, ProviderLoader.LoadConfiguration(u.GetType().ToString()));
							Collectors.DisabledUsersProviderCollector.RemoveProvider(u);
							Collectors.UsersProviderCollector.AddProvider(u);
							Users.Instance.LoadFrom(u, true);
							LoadUsers();
						}
						catch {
							err = true;
						}
					}
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.DisabledPagesProviderCollector.GetProvider(name);
					if(p != null) {
						try {
							p.Init(Host.Instance, ProviderLoader.LoadConfiguration(p.GetType().ToString()));
							Collectors.DisabledPagesProviderCollector.RemoveProvider(p);
							Collectors.PagesProviderCollector.AddProvider(p);
							Content.InvalidateAll();
							Content.PseudoCache.Clear();
							Pages.Instance.LoadFrom(p, true);
							Snippets.Instance.LoadFrom(p, true);
							NavigationPaths.Instance.LoadFrom(p, true);
							LoadPages(true);
							LoadCategories();
							LoadSnippets();
							LoadNavPaths();
						}
						catch {
							err = true;
						}
					}
					break;
				case "[F]":
					IFormatterProvider f = Collectors.DisabledFormatterProviderCollector.GetProvider(name);
					if(f != null) {
						try {
							f.Init(Host.Instance, ProviderLoader.LoadConfiguration(f.GetType().ToString()));
							Collectors.DisabledFormatterProviderCollector.RemoveProvider(f);
							Collectors.FormatterProviderCollector.AddProvider(f);
							Content.InvalidateAll();
							Content.PseudoCache.Clear();
						}
						catch {
							err = true;
						}
					}
					break;
				default:
					throw new Exception();
			}

			if(!err) {
				ProviderLoader.SaveStatus(name, true);
				lblProviderResult.CssClass = "resultok";
				lblProviderResult.Text = Resources.Messages.ProviderEnabled;
				LoadProviders();
			}
			else {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderRefusedConfiguration;
			}
		}

		protected void btnDisableProvider_Click(object sender, EventArgs e) {
			lblProviderResult.Text = "";

			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.UsersProviderCollector.GetProvider(name);
					if(u != null) {
						if(u.GetType().ToString().Equals(Settings.DefaultUsersProvider)) {
							lblProviderResult.CssClass = "resulterror";
							lblProviderResult.Text = Resources.Messages.CannotDisableDefaultProvider;
							return;
						}
						Collectors.UsersProviderCollector.RemoveProvider(u);
						Collectors.DisabledUsersProviderCollector.AddProvider(u);
						Users.Instance.UnloadFrom(u);
						u.Shutdown();
						LoadUsers();
					}
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.PagesProviderCollector.GetProvider(name);
					if(p != null) {
						if(p.GetType().ToString().Equals(Settings.DefaultPagesProvider)) {
							lblProviderResult.CssClass = "resulterror";
							lblProviderResult.Text = Resources.Messages.CannotDisableDefaultProvider;
							return;
						}
						Collectors.PagesProviderCollector.RemoveProvider(p);
						Collectors.DisabledPagesProviderCollector.AddProvider(p);
						Content.InvalidateAll();
						Content.PseudoCache.Clear();
						Pages.Instance.UnloadFrom(p);
						Snippets.Instance.UnloadFrom(p);
						NavigationPaths.Instance.UnloadFrom(p);
						p.Shutdown();
						LoadPages(true);
						LoadCategories();
						LoadSnippets();
						LoadNavPaths();
					}
					break;
				case "[F]":
					IFormatterProvider f = Collectors.FormatterProviderCollector.GetProvider(name);
					if(f != null) {
						Collectors.FormatterProviderCollector.RemoveProvider(f);
						Collectors.DisabledFormatterProviderCollector.AddProvider(f);
						f.Shutdown();
						Content.InvalidateAll();
						Content.PseudoCache.Clear();
					}
					break;
				default:
					throw new Exception();
			}

			ProviderLoader.SaveStatus(name, false);
			lblProviderResult.CssClass = "resultok";
			lblProviderResult.Text = Resources.Messages.ProviderDisabled;
			LoadProviders();
		}

		protected void btnUnloadProvider_Click(object sender, EventArgs e) {
			lblProviderResult.Text = "";

			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.UsersProviderCollector.GetProvider(name);
					if(u == null) u = Collectors.DisabledUsersProviderCollector.GetProvider(name);
					if(u == null) return;
					if(u.GetType().ToString().Equals(Settings.DefaultUsersProvider)) {
						lblProviderResult.CssClass = "resulterror";
						lblProviderResult.Text = Resources.Messages.CannotUnloadDefaultProvider;
						return;
					}
					Collectors.UsersProviderCollector.RemoveProvider(u);
					Collectors.DisabledUsersProviderCollector.RemoveProvider(u);
					Users.Instance.UnloadFrom(u);
					u.Shutdown();
					LoadUsers();
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.PagesProviderCollector.GetProvider(name);
					if(p == null) p = Collectors.DisabledPagesProviderCollector.GetProvider(name);
					if(p == null) return;
					if(p.GetType().ToString().Equals(Settings.DefaultPagesProvider)) {
						lblProviderResult.CssClass = "resulterror";
						lblProviderResult.Text = Resources.Messages.CannotUnloadDefaultProvider;
						return;
					}
					Collectors.PagesProviderCollector.RemoveProvider(p);
					Collectors.DisabledPagesProviderCollector.RemoveProvider(p);
					Content.InvalidateAll();
					Content.PseudoCache.Clear();
					Pages.Instance.UnloadFrom(p);
					Snippets.Instance.UnloadFrom(p);
					NavigationPaths.Instance.UnloadFrom(p);
					p.Shutdown();
					LoadPages(true);
					LoadCategories();
					LoadSnippets();
					LoadNavPaths();
					break;
				case "[F]":
					IFormatterProvider f = Collectors.FormatterProviderCollector.GetProvider(name);
					if(f == null) f = Collectors.DisabledFormatterProviderCollector.GetProvider(name);
					if(f == null) return;
					Collectors.FormatterProviderCollector.RemoveProvider(f);
					Collectors.DisabledFormatterProviderCollector.RemoveProvider(f);
					Content.InvalidateAll();
					Content.PseudoCache.Clear();
					f.Shutdown();
					break;
				default:
					throw new Exception();
			}

			lblProviderResult.CssClass = "resultok";
			lblProviderResult.Text = Resources.Messages.ProviderUnloaded;
			LoadProviders();
		}

		protected void btnRemoveDll_Click(object sender, EventArgs e) {
			try {
				File.Delete(Settings.PluginsDirectory + lstDlls.SelectedValue);
			}
			catch { }
			LoadDlls();
		}

		protected void btnUploadDll_Click(object sender, EventArgs e) {
			lblUploadDllResult.Text = "";
			if(!updDll.HasFile) {
				lblUploadDllResult.CssClass = "resulterror";
				lblUploadDllResult.Text = Resources.Messages.YouMustProvideAFile;
				return;
			}
			string filename = updDll.FileName;
			if(!Path.GetExtension(filename).ToLowerInvariant().Equals(".dll")) {
				lblUploadDllResult.CssClass = "resulterror";
				lblUploadDllResult.Text = Resources.Messages.OnlyDllFilesAllowed;
				return;
			}
			if(File.Exists(Settings.PluginsDirectory + filename)) {
				lblUploadDllResult.CssClass = "resulterror";
				lblUploadDllResult.Text = Resources.Messages.FileAlreadyExists;
				return;
			}
			updDll.SaveAs(Settings.PluginsDirectory + filename);
			ProviderLoader.LoadFromAuto(Settings.PluginsDirectory + filename);
			LoadDlls();
			LoadProviders();
			Pages.Instance.Reload();
			Users.Instance.Reload();
			LoadPages(true);
			LoadCategories();
			LoadSnippets();
			LoadNavPaths();
			LoadUsers();
		}

		protected void lstProviders_SelectedIndexChanged(object sender, EventArgs e) {
			string sel = lstProviders.SelectedValue;
			if(sel == null || sel.Length == 0) {
				lblProviderResult.CssClass = "resulterror";
				lblProviderResult.Text = Resources.Messages.ProviderNotFound;
				return;
			}

			lblProviderResult.Text = "";

			string name = sel.Substring(3);
			string type = sel.Substring(0, 3).ToUpperInvariant();

			string url, author, dll, config;

			switch(type) {
				case "[U]":
					IUsersStorageProvider u = Collectors.UsersProviderCollector.GetProvider(name);
					if(u == null) u = Collectors.DisabledUsersProviderCollector.GetProvider(name);
					name = u.Information.Name;
					author = u.Information.Author;
					url = u.Information.Url;
					dll = u.GetType().Assembly.FullName;
					config = ProviderLoader.LoadConfiguration(u.GetType().ToString());
					break;
				case "[P]":
					IPagesStorageProvider p = Collectors.PagesProviderCollector.GetProvider(name);
					if(p == null) p = Collectors.DisabledPagesProviderCollector.GetProvider(name);
					name = p.Information.Name;
					author = p.Information.Author;
					url = p.Information.Url;
					dll = p.GetType().Assembly.FullName;
					config = ProviderLoader.LoadConfiguration(p.GetType().ToString());
					break;
				case "[F]":
					IFormatterProvider f = Collectors.FormatterProviderCollector.GetProvider(name);
					if(f == null) f = Collectors.DisabledFormatterProviderCollector.GetProvider(name);
					name = f.Information.Name;
					author = f.Information.Author;
					url = f.Information.Url;
					dll = f.GetType().Assembly.FullName;
					config = ProviderLoader.LoadConfiguration(f.GetType().ToString());
					break;
				default:
					throw new Exception();
			}
			dll = dll.Substring(0, dll.IndexOf(",")) + ".dll";
			StringBuilder sb = new StringBuilder();
			sb.Append("<big><b>");
			sb.Append(name);
			sb.Append("</b></big><br />");
			sb.Append(@"<a href=""");
			sb.Append(url);
			sb.Append(@""" target=""_blank"">");
			sb.Append(author);
			sb.Append("</a><br />");
			sb.Append(Resources.Messages.LocatedIn);
			sb.Append(": <b>");
			sb.Append(dll);
			sb.Append("</b><br /><br />");
			sb.Append(Resources.Messages.ConfigurationString);
			sb.Append(":<br />");
			sb.Append(@"<code>");
			sb.Append(HttpContext.Current.Server.HtmlEncode(config));
			sb.Append("</code>");

			lblProviderInfo.Text = sb.ToString();
		}

		protected void lstPagesProviderFrom_SelectedIndexChanged(object sender, EventArgs e) {
			lstPagesProviderTo.Items.Clear();
			if(lstPagesProviderFrom.SelectedValue.Equals("-")) {
				btnMovePages.Enabled = false;
				return;
			}
			IPagesStorageProvider[] provs = Collectors.PagesProviderCollector.AllProviders;
			for(int i = 0; i < provs.Length; i++) {
				if(!provs[i].GetType().ToString().Equals(lstPagesProviderFrom.SelectedValue) &&
					!provs[i].ReadOnly) {
					lstPagesProviderTo.Items.Add(new ListItem(provs[i].Information.Name, provs[i].GetType().ToString()));
				}
			}
			if(lstPagesProviderTo.Items.Count > 0) btnMovePages.Enabled = true;
			else btnMovePages.Enabled = false;
		}

		protected void btnMovePages_Click(object sender, EventArgs e) {
			IPagesStorageProvider from = Collectors.PagesProviderCollector.GetProvider(lstPagesProviderFrom.SelectedValue);
			IPagesStorageProvider to = Collectors.PagesProviderCollector.GetProvider(lstPagesProviderTo.SelectedValue);

			DataMover.MovePages(from, to);

			Content.PseudoCache.Clear();
			Content.InvalidateAll();
			Pages.Instance.Reload();

			LoadPages(true);
			LoadCategories();
			LoadSnippets();
			LoadNavPaths();
		}

		protected void lstUsersProviderFrom_SelectedIndexChanged(object sender, EventArgs e) {
			lstUsersProviderTo.Items.Clear();
			if(lstUsersProviderFrom.SelectedValue.Equals("-")) {
				btnMoveUsers.Enabled = false;
				return;
			}
			IUsersStorageProvider[] provs = Collectors.UsersProviderCollector.AllProviders;
			for(int i = 0; i < provs.Length; i++) {
				if(!provs[i].GetType().ToString().Equals(lstUsersProviderFrom.SelectedValue) &&
					!provs[i].ReadOnly) {
					lstUsersProviderTo.Items.Add(new ListItem(provs[i].Information.Name, provs[i].GetType().ToString()));
				}
			}
			if(lstUsersProviderTo.Items.Count > 0) btnMoveUsers.Enabled = true;
			else btnMoveUsers.Enabled = false;
		}

		protected void btnMoveUsers_Click(object sender, EventArgs e) {
			IUsersStorageProvider from = Collectors.UsersProviderCollector.GetProvider(lstUsersProviderFrom.SelectedValue);
			IUsersStorageProvider to = Collectors.UsersProviderCollector.GetProvider(lstUsersProviderTo.SelectedValue);

			DataMover.MoveUsers(from, to);

			Users.Instance.Reload();

			LoadUsers();
		}

		#endregion

		#region Custom Validators

		protected void cvUsername_ServerValidate(object source, ServerValidateEventArgs args) {
			if ((string.Compare(txtUsername.Text.ToLowerInvariant(), "admin") == 0) || (string.Compare(txtUsername.Text.ToLowerInvariant(), "guest") == 0) ) {
				args.IsValid = false;
				return;
			}

			Users u = Users.Instance;
			args.IsValid = (u.Find(txtUsername.Text) == null);
		}
		
		protected void cvPassword1_ServerValidate(object source, ServerValidateEventArgs args) {
			args.IsValid = (string.Compare(txtPassword1.Text, txtPassword2.Text, true) == 0);
		}
		
		protected void cvPassword2_ServerValidate(object source, ServerValidateEventArgs args) {
			args.IsValid = true;
		}

		protected void cvDateTimeFormat_ServerValidate(object source, ServerValidateEventArgs args) {
			try {
				if(txtDateTimeFormat.Text.Length == 0) throw new Exception();
				string.Format("{0:" + txtDateTimeFormat.Text + "}", DateTime.Now);
				args.IsValid = true;
			}
			catch {
				args.IsValid = false;
			}
		}

		protected void cvSmtpAuth_ServerValidate(object source, ServerValidateEventArgs args) {
			if(txtSmtpPassword.Text.Length > 0 && txtSmtpUsername.Text.Length == 0) args.IsValid = false;
			else args.IsValid = true;
		}
		
		#endregion

	}

}
